//import packages
import java.util.ArrayList;
import java.io.*;

//a class that represents a menu
//a menu includes a title, a description
//a short cut key and possibly a submenu
public class menu
{
     //declare attributes
     private String title;
     private String desc;
     private char key;
     //parent is not null if the menu
     //is the submenu of another menu
     private menu parent;
     //chidlren are non-empty if the menu
     //has at least one submenu
     private ArrayList<menu> children = new ArrayList<menu>();
     
     //a constructor
     public menu(String text, String description, char shortcut, menu top, ArrayList<menu> items)
     {
          title=text;
          desc=description;
          key=shortcut;
          parent=top;
          children=items;
     }
     
     //second constructor, less parameters required
     public menu(String text, String description, menu top, char shortcut)
     {
          title=text;
          desc=description;
          key=shortcut;
          parent=top;
     }
     
     //third constructor, least parameters required
     public menu(String text, menu top, char shortcut)
     {
          title=text;
          desc="";
          key=shortcut;
          parent=top;
     }
     
     //functions to set the attributes
     //note that some might not be required
     //but are included for completeness
     public void setText(String text)
     {
          title=text;
     }
     
     public void setDesc(String text)
     {
          desc=text;
     }
     
     public void setKey (char shortcut)
     {    
          //if the key already exists
          //reject change, two menus on the 
          //same level can not have the same key
          boolean taken=false;
          menu parent=this.getParent();
          
          if (parent==null)
               key=shortcut;
          else if (parent.checkKey(shortcut)==0)
               key=shortcut;
          else
               System.out.println("Sorry, this menu already exists");
     }
     
     public void setParent(menu top)
     {
          parent=top;
     }
     
     public void setItems(ArrayList<menu> items)
     {
          children=items;
     }
     
     //functions to get attributes
     //complimentary to the set functions
     public String getText()
     {
          return title;
     }
     
     public String getDesc()
     {
          return desc;
     }
     
     public char getKey()
     {
          return key;
     }   
     
     public menu getParent()
     {
          return parent;
     }
     
     public ArrayList<menu> getItems()
     {
          return children;
     }
     
     //a function to retrieve a specific
     //menu based on the shortcut key
     public menu getItem(char shortcut)
     {
          //check whether there's a menu
          //with the given shortcut key
          int i=this.checkKey(shortcut);
          if (i!=-1)
          {
               return children.get(i);
          }
          else
          System.out.println("No menu corresponding to this shortcut");
          return null;
     }
     
     //a function to retrieve a specific
     //menu based on menu title
     public menu getItem(String title)
     {
          //check whether there's a menu
          //with the given title
          int i=this.checkText(title);
          if (i!=-1)
          {
               return children.get(i);
          }
          else
          System.out.println("No menu corresponding to your command");
          return null;
     }
     
     //this function adds a submenu to an existing menu
     public void addItem(menu item)
     {
          //check whether the submenu to be added already exists
          //or has the same shortcut key as an existing menu
          //if so, do not create it again
          if(checkText(item.getText())==-1&&checkKey(item.getKey())==-1)
               children.add(item);
          else
               System.out.println("Sorry, this menu already exists");
     }
     
     //this function adds a submenu to an existing menu
     //further more, the submenu can be inserted in a specific location (i.e. top, bottom)
     public void addItemOrder(int index, menu item)
     {
          if(checkText(item.getText())==-1&&checkKey(item.getKey())==-1)
          {
               if(index<=children.size()&&index>=0)
               {
                    children.add(index, item);
               }
          }
          else
               System.out.println("menu either already exists or invalid position");
     }
     
     //this function removes an existing submenu
     public void removeSub()
     {
          children.clear();
     }
     
     //this function prints out the submenu of the menu
     public void printSubMenu()
     {
          for (int i=0; i<children.size(); i++)
          {
               menu temp=children.get(i);
               System.out.println(temp.getText()+"    "+temp.getDesc()+" "+temp.getKey());
          }
     }
     
     //this function prints out a menu
     //note that in contrast to the previous method,
     //this method prints out the caller
     public void printMenu()
     {
      
          System.out.println(this.getText()+"   "+this.getDesc()+" "+this.getKey());
     }
     
     //display a list of options the user can perform on the menu
     public void displayOptions()
     {
          //notice that some options differ depending
          //on whether a submenu or a parent menu exists
          String[] output=new String[9];
          if (children.size()==0)
          {
               output[0]="Select menu";
               output[5]="No submenu";
          }
          else
          {
               output[0]="Display submenu";
               output[5]="Delete submenu";
          }
          output[1]="Edit menu title";
          output[2]="Edit menu description";
          output[3]="Edit menu shortcut key";
          output[4]="Add submenu";
          output[6]="Edit user prompt";
          if (parent!=null)
               output[7]="Return to parent menu";
          else
               output[7]="No parent menu accessbile";
          output[8]="Exit program";
          
          for (int i=0; i<output.length; i++)
          {
               System.out.println(i+", "+output[i]);
          }
     }
     
     //the function interprets user's command and responds
     public String interpret(int option) throws Exception
     {
          String reply="no";
          BufferedReader scan = new BufferedReader(new InputStreamReader(System.in) );
          switch (option)
          {
               case 0: 
               {
                    //display submenu
                    if (children.size()!=0)
                    {
                         printSubMenu();
                         reply="sub";
                    }
                    //select this menu and return its shortcut key
                    else
                         reply="done";
                    break;
               }
               case 1:
               {
                    //change menu title
                    System.out.println("Please enter new menu title");
                    this.setText((scan.readLine()).trim());
                    break;
               }
               case 2:
               {
                    //change menu description
                    System.out.println("Please enter new menu description");
                    this.setDesc((scan.readLine()).trim());
                    break;
               }
               case 3:
               {
                    //change menu shortcut key
                    System.out.println("Please enter new shortcut key");
                    this.setKey(((scan.readLine()).trim()).charAt(0));
                    break;
               }
               case 4:
               {
                    //add a submenu
                    String title,desc;
                    char key;
                    System.out.println("Please enter new menu title");
                    title=(scan.readLine()).trim();
                    System.out.println("Please enter new menu description");
                    desc=(scan.readLine()).trim();
                    System.out.println("Please enter new menu shortcut key");
                    key=((scan.readLine()).trim()).charAt(0);
                    this.addItem(new menu(title,desc,this,key));
                    break;
               }
               case 5:
               {
                    //remove the submenu
                    this.removeSub();
                    break;
               }
               case 6:
               {
                    //edit the user prompt
                    reply="userPrompt";
                    break;
               }
               case 7:
               {
                    //return from a submenu
                    if (parent!=null)
                         reply="parent";
                    break;
               }
               case 8:
               {
                    //exit the program
                    reply="exit";
                    break;
               }
               default:
          }
          return reply;
               
     }
     
     //this function checks whether a menu with
     //the given title exists and returns its index
     public int checkText(String text)
     {
          ArrayList<menu> temp=this.getItems();
          if (temp.size()==0)
               return -1;
          else
          {
               for (int i=0; i<temp.size();i++)
               {
                    if(((temp.get(i)).getText()).equalsIgnoreCase(text))
                    {
                         return i;
                    }
               }
               return -1;
          }
     }
     
     //this function checks whether a menu with
     //the given shortcut key exists and returns its index     
     public int checkKey(char shortcut)
     {
          ArrayList<menu> temp=this.getItems();
          if (temp.size()==0)
          {
               return -1;
          }
          else
          {
               for (int i=0; i<temp.size();i++)
               {
                    //check for upper and lower case
                    char value=(temp.get(i)).getKey();
                    char value2=Character.toUpperCase(value);
                    if(shortcut==value||shortcut==value2)
                    {
                         return i;
                    }
               }
               return -1;         
          }
     }
}